package com.htstar.ovms.device.controller;

import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.htstar.ovms.admin.api.feign.EtpInfoFeign;
import com.htstar.ovms.admin.api.vo.EtpInfoSVo;
import com.htstar.ovms.common.core.constant.CommonConstants;
import com.htstar.ovms.common.core.i18n.MsgCode;
import com.htstar.ovms.common.core.util.OvmDateUtil;
import com.htstar.ovms.common.core.util.R;
import com.htstar.ovms.common.log.annotation.SysLog;
import com.htstar.ovms.common.security.service.OvmsUser;
import com.htstar.ovms.common.security.util.SecurityUtils;
import com.htstar.ovms.device.api.constant.ExportRecordConstant;
import com.htstar.ovms.device.api.dto.*;
import com.htstar.ovms.device.api.entity.DeviceTrip;
import com.htstar.ovms.device.api.entity.ExportRecord;
import com.htstar.ovms.device.api.vo.*;
import com.htstar.ovms.device.handle.event.*;
import com.htstar.ovms.device.service.DeviceTripService;
import com.htstar.ovms.device.service.ExportRecordService;
import com.htstar.ovms.device.service.GpsService;
import com.htstar.ovms.device.util.Cp;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;


/**
 * 行程表
 *
 * @author wj
 * @date 2020-06-12 11:38:07
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/devicetrip")
@Api(value = "devicetrip", tags = "行程表管理/Schedule management")
public class DeviceTripController {

    private final DeviceTripService deviceTripService;
    private final GpsService gpsService;
    private final EtpInfoFeign etpInfoFeign;
    private final ExportRecordService exportRecordService;
    private final ApplicationEventPublisher publisher;

    /**
     * 通过设备编号查询行程信息
     *
     * @return
     * @Author HanGuji
     */
    @ApiOperation(value = "通过设备编号查询行程信息/Query itinerary information by device number", notes = "通过设备编号查询行程信息")
    @PostMapping("/page")
    public R<DeviceTripCountTotalVO> getDeviceTripPage(@RequestBody DeviceTripDTO deviceTripDTO) {
        return R.ok(deviceTripService.getTripInfoByDeviceSnPage(deviceTripDTO));
    }

    /**
     * app 历史行程记录
     */
    @ApiOperation(value = "历史行程记录列表/List of historical trip records", notes = "历史行程记录列表")
    @PostMapping("/getTripHistoricalPage")
    public R<Page<TripHistoricalVO>> getTripHistoricalPage(@RequestBody TripHistoricalDTO tripHistoricalDTO) {
        return R.ok(deviceTripService.getTripHistoricalPage(tripHistoricalDTO));
    }

    /**
     * app 本日，本月，本年，按照天数查询行程轨迹
     *
     * @param tripHistoricalDTO
     * @return
     */
    @ApiOperation(value = "本日，本月，本年，按照天数查询行程轨迹/Today, this month, this year, query the itinerary trajectory according to the number of days", notes = "本日，本月，本年，按照天数查询行程轨迹")
    @PostMapping("/getDateTripPage")
    public R getDateTripPage(@RequestBody TripHistoricalDTO tripHistoricalDTO) {
        return R.ok(deviceTripService.getDateTripPage(tripHistoricalDTO));
    }

    /**
     * 统计(月) 数据
     */
    @ApiOperation(value = "统计(月) 数据/Statistics (Monthly) Data", notes = "统计(月) 数据")
    @GetMapping("/getStatisticsTrip")
    public R getStatisticsTrip(@RequestParam(value = "deviceSn") String deviceSn
            , @RequestParam(value = "monthTime") String monthTime) {
        return R.ok(deviceTripService.getStatisticsTrip(deviceSn, monthTime));
    }


    /**
     * 通过id查询行程表
     *
     * @param id id
     * @return R
     */
    @ApiOperation(value = "通过id查询/Query by id", notes = "通过id查询")
    @GetMapping("/{id}")
    public R getById(@PathVariable("id") Integer id) {
        return R.ok(deviceTripService.getById(id));
    }

//    /**
//     * 新增行程表
//     *
//     * @param deviceTrip 行程表
//     * @return R
//     */
//    @ApiOperation(value = "新增行程表", notes = "新增行程表")
//    @SysLog("新增行程表")
//    @PostMapping
//    @PreAuthorize("@pms.hasPermission('device_devicetrip_add')")
//    public R save(@RequestBody DeviceTrip deviceTrip) {
//        return R.ok(deviceTripService.save(deviceTrip));
//    }

    /**
     * 修改行程表
     *
     * @param deviceTrip 行程表
     * @return R
     */
    @ApiOperation(value = "修改行程表/Modify itinerary", notes = "修改行程表")
    @SysLog("修改行程表")
    @PutMapping
    @PreAuthorize("@pms.hasPermission('device_devicetrip_edit')")
    public R updateById(@RequestBody DeviceTrip deviceTrip) {
        return R.ok(deviceTripService.updateById(deviceTrip));
    }

    /**
     * 通过id删除行程表
     *
     * @param id id
     * @return R
     */
    @ApiOperation(value = "通过id删除行程表/Delete schedule by id", notes = "通过id删除行程表")
    @SysLog("通过id删除行程表")
    @DeleteMapping("/{id}")
    @PreAuthorize("@pms.hasPermission('device_devicetrip_del')")
    public R removeById(@PathVariable Integer id) {
        return R.ok(deviceTripService.removeById(id));
    }


    /**
     * 根据轨迹数据得出轨迹回放GPS数据
     */
    @ApiOperation(value = "根据轨迹数据得出轨迹回放GPS数据/Replay GPS data based on the track data", notes = "根据轨迹数据得出轨迹回放GPS数据")
    @GetMapping("/getGPSDataByDeviceSn")
    public R<TripPlaybackVO> getGPSDataByDeviceSn(TripGpsDTO tripGpsDTO) {
        return R.ok(deviceTripService.getGPSDataByDeviceSn(tripGpsDTO));
    }

    /**
     * 行驶报表
     */
    @ApiOperation(value = "行驶报表/Driving report", notes = "行驶报表")
    @PostMapping("/getTripReportForms")
    public R getTripReportForms(@RequestBody TripReportFormsDTO tripReportFormsDTO) {
        return R.ok(deviceTripService.getTripReportForms(tripReportFormsDTO));
    }

    /**
     * 导出行程报表
     */
//    @ApiOperation(value = "导出行程报表", notes = "导出行程报表")
//    @PostMapping("/exportTripReportForms")
    public R exportTripReportForms(@RequestBody ExprotDeviceTripDTO exprotDeviceTripDTO) {
        OvmsUser user = SecurityUtils.getUser();
        if (exprotDeviceTripDTO.getEtpId() == null && user != null) {
            if (user.getEtpId() != CommonConstants.ETP_ID_1) {
                exprotDeviceTripDTO.setEtpId(user.getEtpId());
            } else {
                exprotDeviceTripDTO.setEtpId(null);
            }
        }
        if (Objects.equals(exprotDeviceTripDTO.getEtpId(), null)) {
            exprotDeviceTripDTO.setEtpId(user.getEtpId());
        }
        List<EtpInfoSVo> currentAndParents1 = etpInfoFeign.getCurrentAndParents1(exprotDeviceTripDTO.getEtpId());
        currentAndParents1.forEach(etpInfoSVo -> {
            exprotDeviceTripDTO.setEtpIds(etpInfoSVo.getIds());
        });
        //List<DeviceTripVO> reportFormsVOS = deviceTripService.exportTripReportForms(exprotDeviceTripDTO);
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        RequestContextHolder.setRequestAttributes(servletRequestAttributes, true);//设置子线程共享
        //save export record
        ExportRecord exportRecord = new ExportRecord();
        exportRecord.setEtpId(exprotDeviceTripDTO.getEtpId());
        exportRecord.setExportType(ExportRecordConstant.HISTORICAL_ITINERARY);
        exportRecord.setExportStatus(ExportRecordConstant.EXPORTING);
        exportRecord.setUserId(SecurityUtils.getUser().getId());
        DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss");
        String fileName = "历史行程_" + SecurityUtils.getUser().getId() + "_" + dtf2.format(LocalDateTime.now());
        exportRecord.setExportName(fileName);
        exportRecordService.save(exportRecord);
        exprotDeviceTripDTO.setExportId(exportRecord.getId());
        exprotDeviceTripDTO.setUserId(SecurityUtils.getUser().getId());
        exprotDeviceTripDTO.setFileName(fileName);
        try {
            publisher.publishEvent(new DeviceTripExcelExportEvent(this, exprotDeviceTripDTO));
        } catch (Exception e) {
            exportRecord.setExportStatus(ExportRecordConstant.EXPORT_FAILED);
            exportRecordService.updateById(exportRecord);
            log.error("发布历史行程导出错误");
        }

        //MsgCode.EXPORTING
        return R.ok(MsgCode.EXPORTING.msg());
    }


    /**
     * 导出行程报表
     */
    @ApiOperation(value = "导出行程报表/Export trip report", notes = "导出行程报表")
    @PostMapping("/exportTripReportForms")
    public R exportTripReportForms2(@RequestBody ExprotDeviceTripDTO exprotDeviceTripDTO) {
        Integer etpId = SecurityUtils.getUser().getEtpId();
        if (exprotDeviceTripDTO.getEtpId() == null) exprotDeviceTripDTO.setEtpId(etpId);
        List<EtpInfoSVo> currentAndParents1 = etpInfoFeign.getCurrentAndParents1(exprotDeviceTripDTO.getEtpId());
        currentAndParents1.forEach(etpInfoSVo -> {
            exprotDeviceTripDTO.setEtpIds(etpInfoSVo.getIds());
        });
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        RequestContextHolder.setRequestAttributes(servletRequestAttributes, true);//设置子线程共享

        //save export record
        ExportRecord exportRecord = new ExportRecord();
        exportRecord.setEtpId(etpId);
        exportRecord.setExportType(ExportRecordConstant.HISTORICAL_ITINERARY);
        exportRecord.setExportStatus(ExportRecordConstant.EXPORTING);
        exportRecord.setUserId(SecurityUtils.getUser().getId());
        DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss");
        String fileName = "历史行程_" + SecurityUtils.getUser().getId() + "_" + dtf2.format(LocalDateTime.now());
        exportRecord.setExportName(fileName);
        exportRecordService.save(exportRecord);
        exprotDeviceTripDTO.setExportId(exportRecord.getId());
        exprotDeviceTripDTO.setUserId(SecurityUtils.getUser().getId());
        exprotDeviceTripDTO.setFileName(fileName);
        try {
            publisher.publishEvent(new DeviceTripExcelExportEvent2(this, exprotDeviceTripDTO));
        } catch (Exception e) {
            log.error("发布历史行程导出错误");
        }

        return R.ok(MsgCode.EXPORTING.msg());
    }


    /**
     * 导出模板
     *
     * @param response
     * @param writer
     * @param rows
     * @param fileName
     * @param errorMsg
     */
    private void getExportExcel(HttpServletResponse response, ExcelWriter writer, List<Map<String, Object>> rows, String fileName, String errorMsg) {
        writer.write(rows, true);
        OutputStream out = null;
        try {
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + new String(URLEncoder.encode(
                    fileName + OvmDateUtil.getCstNowDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
                    , "UTF-8").getBytes("UTF-8"), "ISO8859-1") + ".xlsx");
            out = response.getOutputStream();
            writer.flush(out, true);
        } catch (IOException e) {
            log.error(errorMsg, e);
        } finally {
            writer.close();
            IoUtil.close(out);
        }
    }

//    /**
//     * 导出 企业和车牌号查询行程轨迹
//     */
//    @ApiOperation(value = "导出 企业和车牌号查询行程轨迹/Export enterprise and license plate number query itinerary trajectory", notes = "导出 企业和车牌号查询行程轨迹")
//    @PostMapping("/exportTripByEtpAndLicCodes")
//    public void exportTripByEtpAndLicCode(@RequestBody TripInfoExportDTO tripExportDTO, HttpServletResponse response) {
//        DeviceTripListDTO cp = Cp.cp(tripExportDTO, new DeviceTripListDTO());
//        DeviceTripCountTotalVO tripByEtpAndLicCode = deviceTripService.getTripInfoByDeviceSn(cp);
//        if (CollectionUtils.isEmpty(tripByEtpAndLicCode.getDeviceTrips())) {
//            return;
//        }
//        ExcelWriter writer = ExcelUtil.getWriter(true);
//        writer.renameSheet("轨迹信息");
//        List<Map<String, Object>> rows = new ArrayList<>();
//        Map<String, Object> row = null;
//        for (DeviceTripVO tripAndCarInfoVO : tripByEtpAndLicCode.getDeviceTrips()) {
//            row = new LinkedHashMap<>();
//            row.put("车牌号码", tripAndCarInfoVO.getLicCode() == null ? "" : tripAndCarInfoVO.getLicCode());
//            row.put("行程开始时间", tripAndCarInfoVO.getStaTime() == null ? "" : tripAndCarInfoVO.getStaTime());
//            row.put("行程结束时间", tripAndCarInfoVO.getEndTime() == null ? "" : tripAndCarInfoVO.getEndTime());
//            row.put("开始位置", tripAndCarInfoVO.getStaAddr());
//            row.put("结束位置", tripAndCarInfoVO.getEndAddr());
//            rows.add(row);
//        }
//        getExportExcel(response, writer, rows, "轨迹信息", "企业和车牌号查询行程轨迹导出失败");
//    }


    /**
     * 导出 企业和车牌号查询行程轨迹
     */
    @ApiOperation(value = "导出 企业和车牌号查询行程轨迹/Export enterprise and license plate number query itinerary trajectory", notes = "导出 企业和车牌号查询行程轨迹")
    @PostMapping("/exportTripByEtpAndLicCode")
    public R exportTripByEtpAndLicCodes(@RequestBody TripInfoExportDTO tripExportDTO) {
        ExprotDeviceTripDTO cp = Cp.cp(tripExportDTO, new ExprotDeviceTripDTO());

        if (Objects.equals(cp.getEtpId(), null)) {
            cp.setEtpId(SecurityUtils.getUser().getEtpId());
        }
        List<EtpInfoSVo> currentAndParents1 = etpInfoFeign.getCurrentAndParents1(cp.getEtpId());
        currentAndParents1.forEach(etpInfoSVo -> {
            cp.setEtpIds(etpInfoSVo.getIds());
        });
        //DeviceTripCountTotalVO tripByEtpAndLicCode = deviceTripService.getTripInfoByDeviceSn(cp);
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        RequestContextHolder.setRequestAttributes(servletRequestAttributes, true);//设置子线程共享

        //save export record
        ExportRecord exportRecord = new ExportRecord();
        exportRecord.setEtpId(cp.getEtpId());
        exportRecord.setExportType(ExportRecordConstant.TRACK_PLAYBACK);
        exportRecord.setExportStatus(ExportRecordConstant.EXPORTING);
        exportRecord.setUserId(SecurityUtils.getUser().getId());
        DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss");
        String fileName = "轨迹回放_" + SecurityUtils.getUser().getId() + "_" + dtf2.format(LocalDateTime.now());
        exportRecord.setExportName(fileName);
        exportRecordService.save(exportRecord);
        cp.setExportId(exportRecord.getId());
        cp.setUserId(SecurityUtils.getUser().getId());
        cp.setFileName(fileName);
        try {
            publisher.publishEvent(new DeviceTripExcelExportEvent2(this, cp));
        } catch (Exception e) {
            exportRecord.setExportStatus(ExportRecordConstant.EXPORT_FAILED);
            exportRecordService.updateById(exportRecord);
            log.error("发布轨迹报表导出错误");
        }

        return R.ok(MsgCode.EXPORTING.msg());
    }

}
